//设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性：val 和 next。val 是当前节点的值，next 是指向下一个节点的指针
///引用。如果要使用双向链表，则还需要一个属性 prev 以指示链表中的上一个节点。假设链表中的所有节点都是 0-index 的。 
//
// 在链表类中实现这些功能： 
//
// 
// get(index)：获取链表中第 index 个节点的值。如果索引无效，则返回-1。 
// addAtHead(val)：在链表的第一个元素之前添加一个值为 val 的节点。插入后，新节点将成为链表的第一个节点。 
// addAtTail(val)：将值为 val 的节点追加到链表的最后一个元素。 
// addAtIndex(index,val)：在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度，则该节点将附加
//到链表的末尾。如果 index 大于链表长度，则不会插入节点。如果index小于0，则在头部插入节点。 
// deleteAtIndex(index)：如果索引 index 有效，则删除链表中的第 index 个节点。 
// 
//
// 
//
// 示例： 
//
// MyLinkedList linkedList = new MyLinkedList();
//linkedList.addAtHead(1);
//linkedList.addAtTail(3);
//linkedList.addAtIndex(1,2);   //链表变为1-> 2-> 3
//linkedList.get(1);            //返回2
//linkedList.deleteAtIndex(1);  //现在链表是1-> 3
//linkedList.get(1);            //返回3
// 
//
// 
//
// 提示： 
//
// 
// 所有val值都在 [1, 1000] 之内。 
// 操作次数将在 [1, 1000] 之内。 
// 请不要使用内置的 LinkedList 库。 
// 
// Related Topics 设计 链表 👍 321 👎 0


//leetcode submit region begin(Prohibit modification and deletion)
class MyLinkedList {
public:
    class Node {
    public:
        int val;
        Node* next;
    public:
        Node(int value = 0) : val( value ), next( nullptr ) {}

        ~Node() {}
    };

private:
    Node* head;
public:
    int size;
public:
    MyLinkedList() {
        head = new Node( 0 );
        size = 0;
    }

    ~MyLinkedList() {
        Node* ptr = head;
        while (ptr != nullptr) {
            head = head->next;
            delete ptr;
            ptr = head;
        }
    }

    // get(index)：获取链表中第 index 个节点的值。如果索引无效，则返回-1。
    int get(int index) {
        if (index < 0 || index >= size) {
            return -1;
        }
        Node* ptr = head;
        for (int i = 0; i < index; ++i) {
            ptr = ptr->next;
        }
        return ptr->next->val;
    }

    // addAtHead(val)：在链表的第一个元素之前添加一个值为 val 的节点。插入后，新节点将成为链表的第一个节点。
    void addAtHead(int val) {
        Node* node = new Node( val );
        node->next = head->next;
        head->next = node;
        ++size;
    }

    // addAtTail(val)：将值为 val 的节点追加到链表的最后一个元素。
    void addAtTail(int val) {
        Node* ptr = head;
        for (int i = 0; i < size; ++i) {
            ptr = ptr->next;
        }
        Node* node = new Node( val );
        ptr->next = node;
        ++size;
    }

    // addAtIndex(index,val)：在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度，则该节点将附加
    //到链表的末尾。如果 index 大于链表长度，则不会插入节点。如果index小于0，则在头部插入节点。
    void addAtIndex(int index, int val) {
        if (index == size) {
            addAtTail( val );
            // todo 笔记: WC, 终于找到问题了。
//            ++size;
            return;
        }
        if (index > size) {
            return;
        }
        if (index < 0) {
            addAtHead( val );
//            ++size;
            return;
        }
        Node* node = new Node( val );
        Node* ptr = head;
        for (int i = 0; i < index; ++i) {
            ptr = ptr->next;
        }
        node->next = ptr->next;
        ptr->next = node;
        ++size;
    }

    // deleteAtIndex(index)：如果索引 index 有效，则删除链表中的第 index 个节点。
    void deleteAtIndex(int index) {
        if (index < 0 || index >= size) {
            return;
        }
        Node* ptr = head;
        for (int i = 0; i < index; ++i) {
            ptr = ptr->next;
        }
        Node* node = ptr->next;
        ptr->next = ptr->next->next;
        delete node;
        --size;
    }
};

/**
 * Your MyLinkedList object will be instantiated and called as such:
 * MyLinkedList* obj = new MyLinkedList();
 * int param_1 = obj->get(index);
 * obj->addAtHead(val);
 * obj->addAtTail(val);
 * obj->addAtIndex(index,val);
 * obj->deleteAtIndex(index);
 */
//leetcode submit region end(Prohibit modification and deletion)


#include <iostream>

/*
["MyLinkedList","addAtHead","addAtHead","addAtHead","addAtIndex","deleteAtIndex","addAtHead","addAtTail","get","addAtHead","addAtIndex","addAtHead"]
[[],[7],[2],[1],[3,0],[2],[6],[4],[4],[4],[5,0],[6]]
 */
int main(int argc, char** argv) {
    {
        MyLinkedList* obj = new MyLinkedList();
        int param_1 = obj->get( 0 );
        std::cout << param_1 << std::endl;
        obj->addAtHead( 11 );
        obj->addAtTail( 12 );
        obj->addAtIndex( 1, 11 );
        obj->deleteAtIndex( 2 );
        delete obj;
    }

    std::cout << "===================================" << std::endl;

    {
        MyLinkedList myLinkedList;
        std::cout << "myLinkedList.get( 0 ) = " << myLinkedList.get( 0 ) << std::endl;

        myLinkedList.addAtHead( 11 );
        myLinkedList.addAtTail( 12 );
        std::cout << "-----------------" << std::endl;
        for (int i = 0; i < myLinkedList.size; ++i) {
            std::cout << "myLinkedList.get( " << i << " ) = " << myLinkedList.get( i ) << std::endl;
        }
        std::cout << "-----------------" << std::endl;

        myLinkedList.addAtIndex( 0, 0 );
        std::cout << "-----------------" << std::endl;
        for (int i = 0; i < myLinkedList.size; ++i) {
            std::cout << "myLinkedList.get( " << i << " ) = " << myLinkedList.get( i ) << std::endl;
        }
        std::cout << "-----------------" << std::endl;

        myLinkedList.deleteAtIndex( 100 );
        myLinkedList.deleteAtIndex( myLinkedList.size - 1 );
        std::cout << "-----------------" << std::endl;
        for (int i = 0; i < myLinkedList.size; ++i) {
            std::cout << "myLinkedList.get( " << i << " ) = " << myLinkedList.get( i ) << std::endl;
        }
        std::cout << "-----------------" << std::endl;

        myLinkedList.deleteAtIndex( 0 );
        std::cout << "-----------------" << std::endl;
        for (int i = 0; i < myLinkedList.size; ++i) {
            std::cout << "myLinkedList.get( " << i << " ) = " << myLinkedList.get( i ) << std::endl;
        }
        std::cout << "-----------------" << std::endl;

    }

    /*
["MyLinkedList","addAtHead","addAtHead","addAtHead","addAtIndex","deleteAtIndex","addAtHead","addAtTail","get","addAtHead","addAtIndex","addAtHead"]
[[],[7],[2],[1],[3,0],[2],[6],[4],[4],[4],[5,0],[6]]
     */
    {
        MyLinkedList myLinkedList;
        myLinkedList.addAtHead( 7 );
        myLinkedList.addAtHead( 2 );
        myLinkedList.addAtHead( 1 );
        myLinkedList.addAtIndex( 3, 0 );
        myLinkedList.deleteAtIndex( 2 );
        myLinkedList.addAtHead( 6 );
        myLinkedList.addAtTail( 4 );
        myLinkedList.get( 4 );
        myLinkedList.addAtHead( 4 );
        myLinkedList.addAtIndex( 5, 0 );
        myLinkedList.addAtHead( 6 );

    }

    return 0;
}
